package com.project.mq.mqserver.datacenter;

import com.project.mq.common.MqException;
import com.project.mq.mqserver.core.Binding;
import com.project.mq.mqserver.core.Exchange;
import com.project.mq.mqserver.core.MSGQueue;
import com.project.mq.mqserver.core.Message;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 *管理硬盘上的数据.
 *分成两个部分：
 *1. 数据库管理元信息
 *2. 文件管理消息内容
 *上层逻辑如果需要操作硬盘,统一用这个类来使用(上层代码不关心当前数据是存储在文件还是数据库)
 */
public class DiskDataCenter {
    //private String virtualHostName;

    // 管理数据库中的元数据
    private DataBaseManager dataBaseManager = new DataBaseManager();
    // 管理文件中的消息数据
    private MessageFileManager messageFileManager = new MessageFileManager();
    /*public void init(String virtualHostName) {
        //针对上述两个实例进行初始化
        this.virtualHostName = virtualHostName;

        initDir();
        dataBaseManager.init();
        //当前这里是空的方法,只是先烈在这里,一旦后续需要扩展,就在这里初始化即可
        messageFileManager.init();
    }*/
    public void init() {
        //针对上述两个实例进行初始化
        dataBaseManager.init();
        //当前这里是空的方法,只是先烈在这里,一旦后续需要扩展,就在这里初始化即可
        messageFileManager.init();
    }
    // 初始化目录结构
    // virtualHostName 为 default-VirtualHost
    // 则存放数据的目录名为：./data/default-VirtualHost/
    /*private void initDir() {
        File baseDir = new File("./data/" + virtualHostName);
        if (!baseDir.exists()) {
            boolean ok = baseDir.mkdirs();
            if (ok) {
                System.out.println("[DiskDataCenter] 初始化数据目录完成!");
            } else {
                System.out.println("[DiskDataCenter] 初始化数据目录失败!");
            }
        } else {
            System.out.println("[DiskDataCenter] 数据目录已经存在!");
        }
    }*/
    //封装 Exchange ⽅法
    public void insertExchange(Exchange exchange) {
        dataBaseManager.insertExchange(exchange);
    }

    public void deleteExchange(String exchangeName) {
        dataBaseManager.deleteExchange(exchangeName);
    }

    public List<Exchange> selectAllExchanges() {
        return dataBaseManager.selectAllExchanges();
    }
    //封装 Queue ⽅法
    public void insertQueue(MSGQueue queue) throws IOException {
        dataBaseManager.insertQueue(queue);
        //创建队列的同时，不仅仅是把队列对象写到数据库中，还需要创建出对应的目录和文件。
        messageFileManager.createQueueFiles(queue.getName());
    }

    public void deleteQueue(String queueName) throws IOException {
        dataBaseManager.deleteQueue(queueName);
        //删除队列的同时，不仅仅是把队列对象从数据库中删除，还需要删除出对应的目录和文件。
        messageFileManager.destroyQueueFiles(queueName);
    }

    public List<MSGQueue> selectAllQueues() {
        return dataBaseManager.selectAllQueues();
    }
    //封装 Binding ⽅法
    public void insertBinding(Binding binding) {
        dataBaseManager.insertBinding(binding);
    }

    public void deleteBinding(Binding binding) {
        dataBaseManager.deleteBinding(binding);
    }

    public List<Binding> selectAllBindings() {
        return dataBaseManager.selectAllBindings();
    }
    //封装 Message ⽅法
    public void sendMessage(MSGQueue queue, Message message) throws MqException, IOException {
        messageFileManager.sendMessage(queue, message);
    }

    public void deleteMessage(MSGQueue queue, Message message) throws MqException, IOException, ClassNotFoundException {
        messageFileManager.deleteMessage(queue, message);

        // 判定是否要GC
        if (messageFileManager.checkGC(queue.getName())) {
            messageFileManager.gc(queue);
        }
    }

    public LinkedList<Message> loadAllMessageFromQueue(String queueName) throws MqException, IOException, ClassNotFoundException {
        return messageFileManager.loadAllMessageFromQueue(queueName);
    }
}
